<template>
    <div class="app-container" v-loading="loading" element-loading-text="测试拓扑中"
        element-loading-spinner="el-icon-loading">
        <div class="left-menu" style="width:450px;">
            <!-- <span>网元列表</span> -->
            <!-- <div> -->
            <div class="letf_top " style="height: 60%;display: flex;flex-direction: column;">

                <div class="top_content" style="flex: 1; height: 64px;">
                    <div>基础网元</div>
                    <div style="display: flex; flex-direction: row;">
                        <div style="flex: 1; padding: 5px;">
                            <img :src="require('@/assets/images/web.png')" @click="add_web"
                                style="width: 64px; height: 64px;">
                            <div class="icon_text">外部网络</div>
                        </div>
                        <div style="flex: 1; padding: 5px;text-align: center">
                            <img :src="require('@/assets/images/exchange.png')" @click="add_exchange"
                                style="width: 64px; height: 64px;">
                            <div class="icon_text">交换机</div>
                        </div>
                        <div style="flex: 1; padding: 5px;text-align: center">
                            <img :src="require('@/assets/images/router.png')" @click="add_router"
                                style="width: 64px; height: 64px;">
                            <div class="icon_text">路由器</div>
                        </div>
                        <div style="flex: 1; padding: 5px;text-align: center">
                            <img :src="require('@/assets/images/pc.png')" @click="add_vm"
                                style="width: 64px; height: 64px;">
                            <div class="icon_text">PC</div>
                        </div>
                        <div style="flex: 1; padding: 5px;text-align: center">
                            <img :src="require('@/assets/images/container.png')" @click="add_container"
                                style="width: 64px; height: 64px;">
                            <div class="icon_text">容器</div>
                        </div>
                    </div>
                </div>

                <div class="top_content" style="flex: 1;">
                    <span>安全设备</span>
                    <div style="display: flex; flex-direction: row;">
                        <div>
                            <div style="flex: 1;padding: 5px;text-align: center">
                                <img :src="require('@/assets/images/dbstandard.png')" @click="add_dbstandard"
                                    style="width: 64px; height: 64px;">
                                <div class="icon_text">数据库管理</div>
                            </div>
                            <div style="flex: 1;padding: 5px;text-align: center">
                                <img :src="require('@/assets/images/NGFW.png')" @click="add_NGFW"
                                    style="width: 64px; height: 64px;">
                                <div class="icon_text">NGFW</div>
                            </div>
                            <!-- <div style="flex: 1;padding: 5px;text-align: center">
                                <img :src="require('@/assets/images/APT.png')" @click="add_APT"
                                    style="width: 64px; height: 64px;">
                                <div class="icon_text">APT</div>
                            </div> -->
                        </div>
                        <div>
                            <div style="flex: 1;padding: 5px;text-align: center">
                                <img :src="require('@/assets/images/dbcheck.png')" @click="add_dbcheck"
                                    style="width: 64px; height: 64px;">
                                <div class="icon_text">数据库审计</div>
                            </div>
                            <!-- <div style="flex: 1;padding: 5px;text-align: center">
                                <img :src="require('@/assets/images/NGFW.png')" @click="add_NGFW"
                                    style="width: 64px; height: 64px;">
                                <div class="icon_text">NGFW</div>
                            </div> -->
                            <div style="flex: 1;padding: 5px;text-align: center">
                                <img :src="require('@/assets/images/WAF.png')" @click="add_WAF"
                                    style="width: 64px; height: 64px;">
                                <div class="icon_text">WAF</div>
                            </div>
                        </div>

                        <div style="flex: 1;padding: 5px;text-align: center">
                            <img :src="require('@/assets/images/dbsecurity.png')" @click="add_dbsecurity"
                                style="width: 64px; height: 64px;">
                            <div class="icon_text">数据库网关</div>
                        </div>
                       

                        <div style="flex: 1;padding: 5px;text-align: center">
                            <img :src="require('@/assets/images/API.png')" @click="add_api"
                                style="width: 64px; height: 64px;">
                            <div class="icon_text">API接口</div>
                        </div>
                        <!-- <div style="flex: 1;padding: 5px;text-align: center">
                            <img :src="require('@/assets/images/fireWall.png')" @click="add_fireWall"
                                style="width: 64px; height: 64px;">
                            <span class="icon_text">防火墙</span>
                        </div> -->
                        <div style="flex: 1;"></div>
                        <div style="flex: 1;padding: 5px;text-align: center">
                            <img :src="require('@/assets/images/APT.png')" @click="add_APT"
                                style="width: 64px; height: 64px;">
                            <div class="icon_text">APT</div>
                        </div>

                    </div>
                </div>
            </div>

            <div class="left_bottom">
                <el-tabs type="border-card" v-model="activeName">
                    <el-tab-pane label="节点" name="first">Node</el-tab-pane>
                    <el-tab-pane label="设备类型" name="second">
                        <el-input placeholder="请输入内容" prefix-icon="el-icon-search" v-model="input"></el-input>
                    </el-tab-pane>
                    <el-collapse v-model="active_Name" accordion>
                        <el-collapse-item title="终端设备" name="1">
                            <el-table :data="tableData" style="width: 100%">
                                <el-table-column prop="node_name" label="节点名称" width="100">
                                </el-table-column>
                                <el-table-column prop="specification" label="规格" width="180">
                                </el-table-column>
                            </el-table>
                        </el-collapse-item>
                        <el-collapse-item title="网络设备" name="2">

                        </el-collapse-item>
                        <el-collapse-item title="安全设备" name="3">

                        </el-collapse-item>
                    </el-collapse>
                </el-tabs>
                <div style="text-align: center;padding-top: 10px;">
                    <el-button type="primary" @click="save">保存拓扑</el-button>
                    <el-dialog title="保存拓扑图" :visible.sync="dialogVisible" width="30%" @close="handleCancel">
                        <span>请输入该拓扑图的名称</span>
                        <el-input v-model="topologyName" placeholder="拓扑图名称" style="margin-top: 10px;"></el-input>
                        <span slot="footer" class="dialog-footer">
                            <el-button @click="handleCancel">取消</el-button>
                            <el-button type="primary" @click="handleConfirm">确认</el-button>
                        </span>
                    </el-dialog>
                    <el-button type="primary" @click="test" style="margin-left: 40px;">测试拓扑</el-button>
                </div>


            </div>
        </div>
        <div id="mynetwork">

        </div>
    </div>
</template>

<script>
import { selectTopoById, addTopo } from "@/api/topo";
import * as vis from "vis";
export default {
    name: 'WebDefenseVisNetwork',
    data() {
        return {
            activeName: 'second',
            active_Name: 1,
            // Your data properties here
            checked: true,
            nodes: new vis.DataSet([]),
            edges: new vis.DataSet([]),
            network: null,
            dialogVisible: false, // 控制对话框显示与否
            topologyName: '', // 存储用户输入的拓扑图名称
            EDGE_LENGTH_MAIN: 150,
            EDGE_LENGTH_SUB: 50,
            add_nodes_id: 300,
            input1: '',
            tableData: [{
                node_name: '虚拟机',
                specification: 'VM.R1.Micro',
            }, {
                node_name: '容器',
                specification: 'Docker.R1.Micro',
            }],
            input: "",
            selectedNodes: [],  // 选中的节点列表
            nodesList: [],  // 节点列表
            topoId: "",   //拓扑图id
            loading: false
        };
    },
    methods: {
        // 移除节点  
        removeNode(nodeId) {
            this.nodes.remove(nodeId);
            this.edges.remove(this.edges.get({ filter: edge => edge.from === nodeId || edge.to === nodeId }));
        },

        //  移除边
        // removeEdge(fromId, toId) {
        //     this.edges.remove(this.edges.get({ filter: edge => edge.from === fromId && edge.to === toId }));
        // },
        removeEdge(fromId, toId) {
            const edgesToRemove = this.edges.get({
                filter: edge => (edge.from === fromId && edge.to === toId) || (edge.from === toId && edge.to === fromId)
            });
            this.edges.remove(edgesToRemove);  // 删除符合条件的边
        },

        handleNodeClick(nodeId) {
            if (this.selectedNodes.length === 0) {
                // 第一次点击节点，将该节点加入选中列表
                this.selectedNodes.push(nodeId);
            } else if (this.selectedNodes.length === 1) {
                // 第二次点击节点
                const firstNode = this.selectedNodes[0];
                if (firstNode !== nodeId) {
                    // 检查两个节点之间是否已有边
                    const existingEdge = this.edges.get({
                        filter: edge => (edge.from === firstNode && edge.to === nodeId) || (edge.from === nodeId && edge.to === firstNode)
                    });

                    if (existingEdge.length > 0) {
                        // 如果边已存在，弹出是否删除的提示
                        if (confirm("是否删除边？")) {
                            this.removeEdge(firstNode, nodeId);
                        }
                    } else {
                        // 如果边不存在，创建新边
                        this.edges.add({ from: firstNode, to: nodeId, length: this.EDGE_LENGTH_SUB });
                        this.draw_network();
                    }
                } else {
                    // 如果点击的节点是同一个节点，则提示删除节点
                    if (confirm("是否删除此节点？")) {
                        this.removeNode(firstNode);
                    }
                }
                // 清空 `selectedNodes` 以准备下一次点击
                this.selectedNodes = [];
            }
        },

        // 初始化节点和边
        draw() {
            console.log("Initializing nodes and edges...");
            // 创建或更新网络
            this.draw_network();
        },

        // 新增节点功能
        add_exchange() {
            this.nodes.add({
                id: this.add_nodes_id,
                label: "交换机",
                image: require("@/assets/images/exchange.png"),
                shape: "image",
                image_src: "@/assets/images/exchange.png",
                type: 1
            });
            this.add_nodes_id = this.add_nodes_id + 1;
        },

        add_web() {
            this.nodes.add({
                id: this.add_nodes_id,
                label: "外部网络",
                image: require("@/assets/images/web.png"),
                shape: "image",
                image_src: "@/assets/images/web.png",
                type: 2
            });
            this.add_nodes_id = this.add_nodes_id + 1;
        },

        // add_exchange() {
        //     this.nodes.add({
        //         id: this.add_nodes_id,
        //         label: "DMZ_Router",
        //         image: require("@/assets/images/exchange.png"),
        //         shape: "image",
        //         image_src: "@/assets/images/exchange.png",
        //         type: 3
        //     });
        //     this.add_nodes_id = this.add_nodes_id + 1;
        // },

        add_router() {
            this.nodes.add({
                id: this.add_nodes_id,
                label: "路由器",
                image: require("@/assets/images/router.png"),
                shape: "image",
                image_src: "@/assets/images/router.png",
                type: 4
            });
            this.add_nodes_id = this.add_nodes_id + 1;
        },

        add_pc() {
            this.nodes.add({
                id: this.add_nodes_id,
                label: "PC",
                image: require("@/assets/images/pc.png"),
                shape: "image",
                image_src: "@/assets/images/pc.png",
                type: 5
            });
            this.add_nodes_id = this.add_nodes_id + 1;
        },

        add_vm() {
            this.nodes.add({
                id: this.add_nodes_id,
                label: "虚拟机",
                image: require("@/assets/images/vm.png"),
                shape: "image",
                image_src: "@/assets/images/vm.png",
                type: 6
            });
            this.add_nodes_id = this.add_nodes_id + 1;
        },

        add_container() {
            this.nodes.add({
                id: this.add_nodes_id,
                label: "容器",
                image: require("@/assets/images/container.png"),
                shape: "image",
                image_src: "@/assets/images/container.png",
                type: 7
            });
            this.add_nodes_id = this.add_nodes_id + 1;
        },

        add_dbcheck() {
            this.nodes.add({
                id: this.add_nodes_id,
                label: "数据库审计",
                image: require("@/assets/images/dbcheck.png"),
                shape: "image",
                image_src: "@/assets/images/dbcheck.png",
                type: 8
            });
            this.add_nodes_id = this.add_nodes_id + 1;
        },

        add_dbstandard() {
            this.nodes.add({
                id: this.add_nodes_id,
                label: "数据库管理",
                image: require("@/assets/images/dbstandard.png"),
                shape: "image",
                image_src: "@/assets/images/dbstandard.png",
                type: 9
            });
            this.add_nodes_id = this.add_nodes_id + 1;
        },

        add_dbsecurity() {
            this.nodes.add({
                id: this.add_nodes_id,
                label: "数据库网关",
                image: require("@/assets/images/dbsecurity.png"),
                shape: "image",
                image_src: "@/assets/images/dbsecurity.png",
                type: 10
            });
            this.add_nodes_id = this.add_nodes_id + 1;
        },

        add_api() {
            this.nodes.add({
                id: this.add_nodes_id,
                label: "API接口",
                image: require("@/assets/images/API.png"),
                shape: "image",
                image_src: "@/assets/images/API.png",
                type: 11
            });
            this.add_nodes_id = this.add_nodes_id + 1;
        },
        add_NGFW() {
            this.nodes.add({
                id: this.add_nodes_id,
                label: "NGFW",
                image: require("@/assets/images/NGFW.png"),
                shape: "image",
                image_src: "@/assets/images/NGFW.png",
                type: 12
            });
            this.add_nodes_id = this.add_nodes_id + 1;
        },
        add_WAF() {
            this.nodes.add({
                id: this.add_nodes_id,
                label: "WAF",
                image: require("@/assets/images/WAF.png"),
                shape: "image",
                image_src: "@/assets/images/WAF.png",
                type: 13
            });
            this.add_nodes_id = this.add_nodes_id + 1;
        },
        add_APT() {
            this.nodes.add({
                id: this.add_nodes_id,
                label: "APT",
                image: require("@/assets/images/APT.png"),
                shape: "image",
                image_src: "@/assets/images/APT.png",
                type: 14
            });
            this.add_nodes_id = this.add_nodes_id + 1;
        },
        // 创建或更新网络图
        draw_network() {
            var container = document.getElementById("mynetwork");

            var data = {
                nodes: this.nodes, // 使用 vis.js 的 DataSet 更新节点数据
                edges: this.edges, // 使用 vis.js 的 DataSet 更新边数据
            };
            var options = {
                locale: "cn"
            };

            //如果网络实例尚未创建，则创建它
            //if (!this.network) {
            this.network = new vis.Network(container, data, options);
            //}
            console.log("111")
            // 监听节点点击事件
            this.network.on("click", (params) => {
                if (params.nodes.length > 0) {
                    // 如果点击了节点，处理节点点击事件
                    this.handleNodeClick(params.nodes[0]);
                }
            });

        },

        selectTopoById(topoId) {
            //根据topoId查询拓扑图数据
            selectTopoById(topoId).then(response => {
                var res = response.data;
                var max_node_id = this.add_nodes_id;
                var nodes = [];
                res.nodes.forEach(node => {

                    var rq;
                    if (node.type == null) {
                        rq = require("@/assets/images/exchange.png");
                    }
                    if (node.type == 1) {
                        rq = require("@/assets/images/exchange.png");
                    }
                    else if (node.type == 2) {
                        rq = require("@/assets/images/web.png");
                    }
                    else if (node.type == 3) {
                        rq = require("@/assets/images/exchange.png");
                    }
                    else if (node.type == 4) {
                        rq = require("@/assets/images/router.png");
                    }
                    else if (node.type == 5) {
                        rq = require("@/assets/images/dataServer.png");
                    }
                    else if (node.type == 6) {
                        rq = require("@/assets/images/vm.png");
                    }
                    else if (node.type == 7) {
                        rq = require("@/assets/images/container.png");
                    }
                    else if (node.type == 8) {
                        rq = require("@/assets/images/dbcheck.png");
                    }
                    else if (node.type == 9) {
                        rq = require("@/assets/images/dbstandard.png");
                    }
                    else if (node.type == 10) {
                        rq = require("@/assets/images/dbsecurity.png");
                    }
                    else if (node.type == 11) {
                        rq = require("@/assets/images/API.png");
                    }
                    else if (node.type == 12) {
                        rq = require("@/assets/images/NGFW.png");
                    }
                    else if (node.type == 13) {
                        rq = require("@/assets/images/WAF.png");
                    }
                    else if (node.type == 14) {
                        rq = require("@/assets/images/APT.png");
                    }
                    if (node.nodeId > max_node_id) {
                        max_node_id = node.nodeId;
                    }
                    nodes.push({
                        id: node.nodeId,
                        label: node.label,
                        image: rq,
                        shape: node.shape,
                        image_src: node.image
                    });
                });
                var edges = []
                res.edges.forEach(edge => {
                    edges.push({
                        from: edge.fromNode,
                        to: edge.toNode,
                        length: edge.length
                    });
                });
                this.nodes = new vis.DataSet(nodes);
                this.edges = new vis.DataSet(edges);
                this.draw();
                this.add_nodes_id = max_node_id + 1;
                console.log("max_nodeId" + this.add_nodes_id);
            });

        },
        save() {
            this.dialogVisible = true; // 打开对话框

        },

        sleep(time) {
            var timeStamp = new Date().getTime();
            var endTime = timeStamp + time;
            while (true) {
                if (new Date().getTime() > endTime) {
                    return;
                }
            }
        },
        handleCancel() {
            this.dialogVisible = false;
            this.topologyName = '';
        },
        handleConfirm() {
            var nodes = []

            this.nodes.forEach(node => {
                nodes.push({ nodeId: node.id, label: node.label, shape: node.shape, image: node.image_src, type: node.type });
            });

            var edges = []
            this.edges.forEach(edge => {
                edges.push({ fromNode: edge.from, toNode: edge.to, length: edge.length });
            });

            // var topoName = "test";
            if (this.topoId) {
                var data = { "topoId": this.topoId, "topoName": this.topologyName, "nodes": nodes, "edges": edges };
            }
            else {
                var data = { "topoName": this.topologyName, "nodes": nodes, "edges": edges };
            }
            // addTopo(data);
            addTopo(data).then(response => {
                console.log(response);
                // if(flag==1)
                this.$message.success("保存成功");
            });
            this.dialogVisible = false;
            this.topologyName = '';
        },
        test() {
            console.log("测试拓扑图");
            this.loading = true;
            var that = this;
            var loadingSeconds = Math.floor(Math.random() * 5)
            console.log(loadingSeconds)

            setTimeout(function () {
                that.loading = false;
                that.$message.success("测试拓扑完成");
            }, loadingSeconds * 1000)
        }
    },

    // 在组件挂载时初始化节点和网络图
    mounted() {
        // this.draw(); // 初始化图表
        if (this.$route.query.topoId) {
            this.topoId = this.$route.query.topoId;
            this.selectTopoById(this.topoId);
            console.log(this.topoId);
            //根据路由传递的topoId查询拓扑图数据
        } else {
            // this.sleep(1000);

            // this.sleep(1000);
            setTimeout(() => {
                this.add_exchange();
            }, 1);

            // this.sleep(1000);
            setTimeout(() => {
                this.add_router();
            }, 1000);

            setTimeout(() => {
                this.edges.add({ from: 300, to: 301, length: this.EDGE_LENGTH_SUB });
            }, 2000)

            setTimeout(() => {
                this.draw_network();
            }, 2100)
            //------------------------------------
            setTimeout(() => {
                this.add_exchange();
            }, 3100)
            setTimeout(() => {
                this.edges.add({ from: 301, to: 302, length: this.EDGE_LENGTH_SUB });
            }, 4100)
            setTimeout(() => {
                this.draw_network();
            }, 4200)
            setTimeout(() => {
                this.edges.add({ from: 300, to: 302, length: this.EDGE_LENGTH_SUB });
            }, 5100)
            setTimeout(() => {
                this.draw_network();
            }, 5200)
            setTimeout(() => {
                this.add_NGFW();
            }, 5200)
            setTimeout(() => {
                this.edges.add({ from: 301, to: 303, length: this.EDGE_LENGTH_SUB });
            }, 6100)
            setTimeout(() => {
                this.draw_network();
            }, 6200)

            setTimeout(() => {
                this.add_web();
            }, 7200)
            setTimeout(() => {
                this.edges.add({ from: 303, to: 304, length: this.EDGE_LENGTH_SUB });
            }, 8100)
            setTimeout(() => {
                this.draw_network();
            }, 8200)
            setTimeout(() => {
                this.add_dbstandard();
            }, 9200)
            setTimeout(() => {
                this.edges.add({ from: 302, to: 305, length: this.EDGE_LENGTH_SUB });
            }, 10100)
            setTimeout(() => {
                this.draw_network();
            }, 10200)
            setTimeout(() => {
                this.add_pc();
            }, 11200);
            setTimeout(() => {
                this.edges.add({ from: 300, to: 306, length: this.EDGE_LENGTH_SUB });
            }, 12200)
            setTimeout(() => {
                this.draw_network();
            }, 12300)
            setTimeout(() => {
                this.add_dbcheck();
            }, 13300);
            setTimeout(() => {
                this.edges.add({ from: 302, to: 307, length: this.EDGE_LENGTH_SUB });
            }, 14300)
            setTimeout(() => {
                this.draw_network();
            }, 14400)
            setTimeout(() => {
                this.add_pc();
            }, 13300);
            setTimeout(() => {
                this.edges.add({ from: 300, to: 308, length: this.EDGE_LENGTH_SUB });
            }, 14300)
            setTimeout(() => {
                this.draw_network();
            }, 14400)
            setTimeout(() => {
                this.add_WAF();
            }, 15300);
            setTimeout(() => {
                this.edges.add({ from: 301, to: 309, length: this.EDGE_LENGTH_SUB });
            }, 16300)
            setTimeout(() => {
                this.draw_network();
            }, 16400)
            setTimeout(() => {
                this.add_APT();
            }, 17400);
            setTimeout(() => {
                this.edges.add({ from: 300, to: 310, length: this.EDGE_LENGTH_SUB });
            }, 18400)
            setTimeout(() => {
                this.edges.add({ from: 301, to: 310, length: this.EDGE_LENGTH_SUB });
            }, 18500)
            setTimeout(() => {
                this.edges.add({ from: 302, to: 310, length: this.EDGE_LENGTH_SUB });
            }, 18600)
            setTimeout(() => {
                this.draw_network();
            }, 18800)
            setTimeout(() => {
                this.add_pc();//311
            }, 19800);
            setTimeout(() => {
                this.add_pc();//312
            }, 20800);
            setTimeout(() => {
                this.edges.add({ from: 311, to: 302, length: this.EDGE_LENGTH_SUB });
            }, 21800)
            setTimeout(() => {
                this.edges.add({ from: 312, to: 302, length: this.EDGE_LENGTH_SUB });
            }, 22800)
            setTimeout(() => {
                this.draw_network();
            }, 23000)

        }
    }
}

</script>


<style scoped>
#mynetwork {
    width: 100%;
    height: 800px;
    border: 1px solid #958a8a;
    background-color: #ffffff;

}

.app-container {
    display: flex;
    flex-direction: row;
}

.icon_text {
    font-family: "微软雅黑";
    font-size: 18px;
    text-align: center;
    width: 64px;
}

.left-menu {
    width: 450px;
    height: 800px;
    border: 1px solid #d3d3d3;
    /* 添加灰色的边框 */
    border-radius: 5px;
    /* 添加圆角 */
    padding: 10px;
    /* 增加一些内边距 */
    background-color: #f9f9f9;
    /* 增加背景颜色 */
    margin: top 10px;
}
</style>
